package com.gitee.ywj1352.proxy.dynamic.jdk;

import java.io.FileOutputStream;
import sun.misc.ProxyGenerator;

/**
 * Created by wenjie.yang on 3/25/2019.
 */
public class Test {

  public static void main(String[] args) {
    PersonProxy personProxy = new PersonProxy();
    try {
      //jdk 强制规定 被代理类必须实现 接口 不然 报 类转换异常
      //此时 Man 实现类是 代理类
      Man instance = (Man)personProxy.getInstance(new Person());
      instance.doSomething();
      instance.doWork();
      System.out.println(instance.getClass());
      //原理
      //1.拿到被代理对象的引用,并且获取他的所以接口.反射获取
      //2.JDK proxy 类重新生成一个新的类,同时新的类型要实现被代理类的全部接口
      //3.动态的生成java 代码 把新加的业务逻辑的方法 由一定的逻辑代码去调用(在代码中体现)
          /**
           * public final void doSomething() throws  {
           *         try {
           *              //h 为InvocationHandler 对象
           *              //这里实际调用的是加强类
           *             super.h.invoke(this, m4, (Object[])null);
           *         } catch (RuntimeException | Error var2) {
           *             throw var2;
           *         } catch (Throwable var3) {
           *             throw new UndeclaredThrowableException(var3);
           *         }
           *     }
           */

      //4.编译新生成的java代码.class
      //5.再重现加载到jvm 中
      //以上的过程称为字节码重组

      //jdk中有个规范,只要有个$开头一般都是 自动生成的内部内

      //通过反编译工具查看源码
      byte[] $Proxy0s = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{Person.class});
      FileOutputStream os = new FileOutputStream("d://work//$Proxy0.class");
      os.write($Proxy0s);
      os.close();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

}
